package cn.catsdad.tenant.sqlInspector;

import cn.catsdad.util.AuthUtil;
import cn.catsdad.util.StringUtil;
import org.hibernate.resource.jdbc.spi.StatementInspector;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author xuyl
 * @version 1.0 2024/7/23
 */
public class TenantStatementInspector implements StatementInspector {

    private final List<String> sqlKeyWords = Arrays.asList("where", "left", "right", "cross", "inner", "full",
            "group", "with", "having", "limit", "order", "using", "having");
    String from = "\\bfrom\\b\\s+(\\w+\\s+\\w+)";
    String join = "\\bjoin\\b\\s+(\\w+\\s+\\w+)";
    Pattern fromPattern = Pattern.compile(from);
    Pattern joinPattern = Pattern.compile(join);

    @Override
    public String inspect(String s) {
        StringBuilder result = new StringBuilder(s);
        if (s.contains("select")) {
            Matcher fromMatcher = fromPattern.matcher(s);
            //from后处理
            if (fromMatcher.find()) {
                String tableName = fromMatcher.group(1);
                appendTenantId(tableName, result);
            }
            //join后处理
            Matcher joinMatcher = fromPattern.matcher(s);
            while (joinMatcher.find()) {
                String tableAndAlias = joinMatcher.group(1);
                appendTenantId(tableAndAlias, result);
            }
        }
        return result.toString();
    }

    /**
     * 拼接租户id
     *
     * @param tableAndAlias 表名
     * @param result        sql
     */
    private void appendTenantId(String tableAndAlias, StringBuilder result) {
        if (StringUtil.isNotEmpty(tableAndAlias)) {
            String[] tableAndAliasArr = tableAndAlias.split(" ");
            if (StringUtil.isNotEmpty(tableAndAliasArr) && tableAndAliasArr.length == 2) {
                String queryAlias = tableAndAliasArr[1];
                String tenantId = " tenantId = " + AuthUtil.getCurrentTenantId();
                if (!sqlKeyWords.contains(queryAlias)) {
                    tenantId = queryAlias + ".tenantId = " + AuthUtil.getCurrentTenantId();
                }
                if (result.indexOf(tenantId) < 0) {
                    if (result.indexOf("where") < 0 && result.indexOf("where 1=1") < 0) {
                        result.append(" where ").append(tenantId).append(" ");
                    } else if (result.indexOf("where 1=1") < 0 && result.indexOf("where") >= 0) {
                        int insertPosition = result.indexOf("where") + "where".length();
                        result.insert(insertPosition, " " + tenantId + " and ");
                    } else {
                        int insertPosition = result.indexOf("where 1=1") + "where 1=1".length();
                        result.insert(insertPosition, " and " + tenantId + " ");
                    }
                }
            }
        }
    }
}
